#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>

using namespace std;

//控制线程
volatile bool quit = false;
//线程数量
#define TNUM 4
//函数指针
typedef void* (*run_t)(const string& name,pthread_mutex_t* pmtx,pthread_cond_t* pcond);
//全局或静态的创建条件变量
//pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void* run1(const string& name,pthread_mutex_t* pmtx,pthread_cond_t* pcond)
{   while(!quit){
    //wait一定要在加锁和解锁间进行等待，保证原子性
    pthread_mutex_lock(pmtx);
    pthread_cond_wait(pcond,pmtx);
    cout << name << " A running..." << endl;
    pthread_mutex_unlock(pmtx);
    }
}
void* run2(const string& name,pthread_mutex_t* pmtx,pthread_cond_t* pcond)
{
    while(!quit){
    pthread_mutex_lock(pmtx);
    pthread_cond_wait(pcond,pmtx);
    cout << name << " B running..." << endl;
    pthread_mutex_unlock(pmtx);}
}
void* run3(const string& name,pthread_mutex_t* pmtx,pthread_cond_t* pcond)
{
    while(!quit){
    pthread_mutex_lock(pmtx);
    pthread_cond_wait(pcond,pmtx); 
    cout << name << " C running..." << endl;
    pthread_mutex_unlock(pmtx);}
}
void* run4(const string& name,pthread_mutex_t* pmtx,pthread_cond_t* pcond)
{
    while(!quit){
    pthread_mutex_lock(pmtx);
    pthread_cond_wait(pcond,pmtx);
    cout << name << " D running..." << endl;
    pthread_mutex_unlock(pmtx);}
}

//存储线程相关数据
class ThreadData{
public:
    ThreadData(const string n,run_t r,pthread_mutex_t* p1,pthread_cond_t* p2)
    :_name(n),_run(r),_pcond(p2),_pmtx(p1){}
public:
    string _name;
    run_t _run;
    pthread_mutex_t *_pmtx;
    pthread_cond_t *_pcond;
};

//每一个进程的入口
//可以统一进行资源强转和回收
void* Enter(void* args)
{
    ThreadData* td = (ThreadData*) args;
    td->_run(td->_name,td->_pmtx,td->_pcond);
    delete td;
    return nullptr;
}

int main()
{
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx,nullptr);
    pthread_cond_init(&cond,nullptr);


    pthread_t t[TNUM];
    run_t array[TNUM] = {run1,run2,run3,run4};
    //创建线程
    for(int i = 0;i < TNUM;i++)
    {
        string name = "thread ";
        name += to_string(i+1);
        ThreadData* td = new ThreadData(name,array[i],&mtx,&cond);
        pthread_create(t+i,nullptr,Enter,(void*)td);
    }
    //控制线程
    // while(true)
    // {
    //     //pthread_cond_signal(&cond);
    //     //广播
    //     cout << "resume thread run code ...." << endl;
    //     pthread_cond_broadcast(&cond);
    //     sleep(1);
    // }

    int cnt = 10;
    while(cnt)
    {
        std::cout << "resume thread run code ...." << cnt-- << std::endl;
        pthread_cond_signal(&cond);
        // pthread_cond_broadcast(&cond);
        sleep(1);
    }

    cout << "ctrl done" << endl;
    quit = true;
    pthread_cond_broadcast(&cond);

    //等待线程
    for(int i = 0;i < TNUM;i++)
    {
        pthread_join(t[i],nullptr);
        cout << "quit : " << *(t+i) << endl;
    }
    //释放锁和条件变量
    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);
    return 0;
}